#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <IOKit/hid/IOHIDLib.h>
#include <CoreFoundation/CoreFoundation.h>
#include <pthread.h>
#include <sys/time.h>
#include "logger.h"
#include "headset.h"

// 支持多个耳机设备定义
typedef struct {
    unsigned short vid;
    unsigned short pid;
    char* name;
    int protocol_type; // 协议类型：0=标准，1=华为，2=苹果，等等
} HeadsetDevice;

// 已知支持的耳机设备列表
static const HeadsetDevice known_devices[] = {
    {0x12D1, 0x3A07, "Huawei Headset", 1},   // 华为耳机
    {0x05AC, 0x12A8, "Apple Headset", 2},    // 苹果耳机示例
    {0x046D, 0x0A38, "Logitech Headset", 0}, // 罗技耳机示例
    {0x1532, 0x0504, "Razer Headset", 0},    // 雷蛇耳机示例
    {0x045E, 0x070F, "Microsoft Headset", 0} // 微软耳机示例
    // 可以继续添加更多设备
};

#define NUM_KNOWN_DEVICES (sizeof(known_devices) / sizeof(HeadsetDevice))
// 当前设备的协议类型
static int current_protocol_type = 0;

// 新增超时和双击检测常量
#define WAIT_TIMEOUT_MS      200  // 等待超时时间(毫秒)
#define DOUBLECLICK_TIME_MS  200  // 双击时间阈值(毫秒)
// 添加按键重复触发相关常量
#define KEY_REPEAT_DELAY_MS  500  // 首次重复延迟(毫秒)
#define KEY_REPEAT_RATE_MS   100  // 重复速率(毫秒)
// 添加长按检测相关常量
#define LONG_PRESS_TIME_MS   1000 // 长按触发时间(毫秒)

// IOKit 全局变量
static IOHIDManagerRef gIOHIDManagerRef = NULL;
static CFRunLoopRef gRunLoop = NULL;
static int gDeviceFound = 0;
static int gIsRunning = 0;
static pthread_t gThreadID;
static pthread_mutex_t gMutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t gCond = PTHREAD_COND_INITIALIZER;

// 按键状态跟踪
static HeadsetButton gCurrentButton = BUTTON_NONE;
static unsigned long gLastEventTime = 0;
static unsigned long gLastPlayPauseTime = 0;
static int gPlayPauseClickCount = 0;
static int gIsLongPressDetected = 0;
static unsigned long gPressStartTime = 0;

// 辅助函数：获取毫秒级时间戳
static unsigned long get_time_ms() {
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
}

// 设备匹配回调
static void device_matching_callback(void *context, IOReturn result, void *sender, IOHIDDeviceRef device) {
    if (device) {
        int32_t vendor_id = 0, product_id = 0;
        CFNumberRef vendor_ref = (CFNumberRef)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDVendorIDKey));
        CFNumberRef product_ref = (CFNumberRef)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductIDKey));
        
        if (vendor_ref && product_ref) {
            CFNumberGetValue(vendor_ref, kCFNumberSInt32Type, &vendor_id);
            CFNumberGetValue(product_ref, kCFNumberSInt32Type, &product_id);
            
            dlog("Headset: HID device VID=0x%04X, PID=0x%04X\n", (unsigned short)vendor_id, (unsigned short)product_id);
            
            // 检查是否为已知设备
            for (int i = 0; i < NUM_KNOWN_DEVICES; i++) {
                if ((unsigned short)vendor_id == known_devices[i].vid && 
                    (unsigned short)product_id == known_devices[i].pid) {
                    ilog("  supported headset device: %s\n", known_devices[i].name);
                    current_protocol_type = known_devices[i].protocol_type;
                    gDeviceFound = 1;
                    return;
                }
            }
            
            // 检查是否为通用音频设备
            CFStringRef product_name = (CFStringRef)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey));
            if (product_name && CFGetTypeID(product_name) == CFStringGetTypeID()) {
                char name[256] = {0};
                if (CFStringGetCString(product_name, name, sizeof(name), kCFStringEncodingUTF8)) {
                    dlog("  device name: %s\n", name);
                    
                    // 转换为小写以便比较
                    char lower_name[256] = {0};
                    strncpy(lower_name, name, sizeof(lower_name) - 1);
                    lower_name[sizeof(lower_name) - 1] = '\0'; // 确保字符串以null结尾
                    for (char *p = lower_name; *p; ++p) {
                        *p = tolower(*p);
                    }   
                    
                    // 检查是否包含耳机相关关键词
                    if (strstr(lower_name, "headset") || 
                        strstr(lower_name, "earphone") ||
                        strstr(lower_name, "headphone") ||
                        strstr(lower_name, "audio")) {
                        ilog("  %s: generic audio device\n", name);
                        current_protocol_type = 0; // 使用标准协议
                        gDeviceFound = 1;
                        return;
                    }
                }
            }
            dlog("  not a supported headset device\n");
        }
    }
}

// 输入值回调函数
static void input_value_callback(void *context, IOReturn result, void *sender, IOHIDValueRef value) {
    if (!value) return;
    
    IOHIDElementRef element = IOHIDValueGetElement(value);
    if (!element) return;
    
    uint32_t usage_page = IOHIDElementGetUsagePage(element);
    uint32_t usage = IOHIDElementGetUsage(element);
    CFIndex int_value = IOHIDValueGetIntegerValue(value);
    
    // 基于 Consumer Page (0x0C) 处理多媒体控制按键
    if (usage_page == 0x0C) {
        HeadsetButton button = BUTTON_NONE;
        unsigned long current_time = get_time_ms();
        
        // 映射消费类控制按键到耳机按钮
        switch (usage) {
            case 0xE9:  // Volume Increment
                button = (int_value > 0) ? BUTTON_VOLINC : BUTTON_NONE;
                break;
                
            case 0xEA:  // Volume Decrement
                button = (int_value > 0) ? BUTTON_VOLDDEC : BUTTON_NONE;
                break;
                
            case 0xB0:  // Play
            case 0xB1:  // Pause
            case 0xCD:  // Play/Pause Toggle
                if (int_value > 0) {
                    // 按键按下
                    gPressStartTime = current_time;
                    
                    // 检测是否为双击
                    if (gPlayPauseClickCount > 0 && 
                        (current_time - gLastPlayPauseTime) < DOUBLECLICK_TIME_MS) {
                        // 是双击，重置计数器并设置为NEXT
                        gPlayPauseClickCount = 0;
                        button = BUTTON_NEXT;
                    } else {
                        // 记录第一次点击
                        gPlayPauseClickCount = 1;
                        gLastPlayPauseTime = current_time;
                        // 等待可能的第二次点击，先不设置按钮
                        return;
                    }
                } else {
                    // 按键释放
                    if (gPressStartTime > 0 && !gIsLongPressDetected) {
                        // 非长按释放
                        if (gPlayPauseClickCount == 1 && 
                            (current_time - gLastPlayPauseTime) > DOUBLECLICK_TIME_MS) {
                            // 单击判定
                            button = BUTTON_PLAYPAUSE;
                            gPlayPauseClickCount = 0;
                        }
                    }
                    gIsLongPressDetected = 0;
                    gPressStartTime = 0;
                }
                break;
                
            case 0xB5:  // Scan Next Track
                button = (int_value > 0) ? BUTTON_NEXT : BUTTON_NONE;
                break;
                
            case 0xB6:  // Scan Previous Track
                button = (int_value > 0) ? BUTTON_PREV : BUTTON_NONE;
                break;
                
            case 0x23B:  // 可能的耳机按钮 (苹果协议)
                if (current_protocol_type == 2) { // 苹果协议
                    if (int_value > 0) {
                        // 按钮被按下
                        gPressStartTime = current_time;
                    } else {
                        // 按钮被释放
                        uint64_t press_duration = current_time - gPressStartTime;
                        
                        if (press_duration < 300) {
                            // 短按 = 播放/暂停
                            button = BUTTON_PLAYPAUSE;
                        } else if (press_duration < 800) {
                            // 中按 = 下一曲
                            button = BUTTON_NEXT;
                        } else {
                            // 长按 = 上一曲
                            button = BUTTON_PREV;
                        }
                        gPressStartTime = 0;
                    }
                }
                break;
        }
        
        // 处理长按检测
        if (gPressStartTime > 0 && !gIsLongPressDetected && 
            (current_time - gPressStartTime) > LONG_PRESS_TIME_MS) {
            gIsLongPressDetected = 1;
            button = BUTTON_PREV; // 长按通常映射为上一曲
        }
        
        if (button != BUTTON_NONE) {
            pthread_mutex_lock(&gMutex);
            gCurrentButton = button;
            gLastEventTime = current_time;
            pthread_cond_signal(&gCond);
            pthread_mutex_unlock(&gMutex);
        }
    }
}

// 初始化 IOHIDManager
static int init_hid_manager() {
    // 创建 IOHIDManager
    gIOHIDManagerRef = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDManagerOptionNone);
    if (!gIOHIDManagerRef) {
        ilog("Headset: Failed to create IOHIDManager\n");
        return 0;
    }
    
    // 设置设备匹配条件
    CFMutableDictionaryRef matching_dict = CFDictionaryCreateMutable(
        kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    
    // 匹配所有消费类设备 (包括耳机控制)
    CFNumberRef usage_page_ref = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &(int){0x0C});
    CFDictionarySetValue(matching_dict, CFSTR(kIOHIDDeviceUsagePageKey), usage_page_ref);
    CFRelease(usage_page_ref);
    
    // 设置匹配条件
    IOHIDManagerSetDeviceMatching(gIOHIDManagerRef, matching_dict);
    CFRelease(matching_dict);
    
    // 注册设备匹配回调
    IOHIDManagerRegisterDeviceMatchingCallback(gIOHIDManagerRef, device_matching_callback, NULL);
    
    // 注册输入值回调
    IOHIDManagerRegisterInputValueCallback(gIOHIDManagerRef, input_value_callback, NULL);
    
    // 调度到当前线程的 Run Loop
    IOHIDManagerScheduleWithRunLoop(gIOHIDManagerRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
    
    // 打开 HID 管理器
    IOReturn ret = IOHIDManagerOpen(gIOHIDManagerRef, kIOHIDManagerOptionNone);
    if (ret != kIOReturnSuccess) {
        ilog("Headset: Failed to open IOHIDManager, error: %d\n", ret);
        return 0;
    }
    
    return 1;
}

// 清理 IOHIDManager
static void cleanup_hid_manager() {
    if (gIOHIDManagerRef) {
        IOHIDManagerUnscheduleFromRunLoop(gIOHIDManagerRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
        IOHIDManagerClose(gIOHIDManagerRef, kIOHIDManagerOptionNone);
        CFRelease(gIOHIDManagerRef);
        gIOHIDManagerRef = NULL;
    }
}

// HID 事件线程
static void* hid_event_thread(void* arg) {
    if (!init_hid_manager()) {
        return NULL;
    }
    
    gIsRunning = 1;
    gRunLoop = CFRunLoopGetCurrent();
    
    // 设置超时检测定时器
    CFRunLoopTimerContext timer_context = {0, NULL, NULL, NULL, NULL};
    CFRunLoopTimerRef timer = CFRunLoopTimerCreate(
        kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + 0.1, 0.1, 0, 0,
        NULL, &timer_context);
    
    CFRunLoopAddTimer(gRunLoop, timer, kCFRunLoopDefaultMode);
    
    // 运行 Run Loop
    while (gIsRunning) {
        CFRunLoopRun();
    }
    
    CFRunLoopRemoveTimer(gRunLoop, timer, kCFRunLoopDefaultMode);
    CFRelease(timer);
    cleanup_hid_manager();
    
    return NULL;
}

// 启动 HID 事件线程
static void start_hid_event_thread() {
    static int thread_started = 0;
    
    if (!thread_started) {
        pthread_create(&gThreadID, NULL, hid_event_thread, NULL);
        thread_started = 1;
    }
}

// 停止 HID 事件线程
static void stop_hid_event_thread() {
    if (gIsRunning && gRunLoop) {
        gIsRunning = 0;
        CFRunLoopStop(gRunLoop);
        pthread_join(gThreadID, NULL);
    }
}

// 获取耳机按键事件
HeadsetButton get_headset_button() {
    static int initialized = 0;
    
    if (!initialized) {
        start_hid_event_thread();
        initialized = 1;
    }
    
    // 如果线程未启动，则返回 NONE
    if (!gIsRunning) {
        usleep(WAIT_TIMEOUT_MS * 1000);
        return BUTTON_NONE;
    }
    
    HeadsetButton button = BUTTON_NONE;
    
    // 加锁访问共享数据
    pthread_mutex_lock(&gMutex);
    
    // 检查长按状态
    unsigned long current_time = get_time_ms();
    if (gPressStartTime > 0 && !gIsLongPressDetected && 
        (current_time - gPressStartTime) > LONG_PRESS_TIME_MS) {
        gIsLongPressDetected = 1;
        gCurrentButton = BUTTON_PREV;
    }
    
    // 检查双击状态
    if (gPlayPauseClickCount == 1 && 
        (current_time - gLastPlayPauseTime) > DOUBLECLICK_TIME_MS) {
        gPlayPauseClickCount = 0;
        gCurrentButton = BUTTON_PLAYPAUSE;
    }
    
    // 获取当前按钮状态
    if (gCurrentButton != BUTTON_NONE) {
        button = gCurrentButton;
        gCurrentButton = BUTTON_NONE;
    } else {
        // 等待按钮事件或超时
        struct timespec ts;
        struct timeval tp;
        gettimeofday(&tp, NULL);
        
        ts.tv_sec = tp.tv_sec;
        ts.tv_nsec = tp.tv_usec * 1000;
        ts.tv_sec += WAIT_TIMEOUT_MS / 1000;
        ts.tv_nsec += (WAIT_TIMEOUT_MS % 1000) * 1000000;
        
        // 处理纳秒溢出
        if (ts.tv_nsec >= 1000000000) {
            ts.tv_sec++;
            ts.tv_nsec -= 1000000000;
        }
        
        pthread_cond_timedwait(&gCond, &gMutex, &ts);
        
        // 再次检查状态
        if (gCurrentButton != BUTTON_NONE) {
            button = gCurrentButton;
            gCurrentButton = BUTTON_NONE;
        }
    }
    
    pthread_mutex_unlock(&gMutex);
    
    if (button != BUTTON_NONE) {
        ilog("Headset: button %d pressed\n", button);
    }
    
    return button;
}

#ifdef TEST
int main() {
    while(1) {
        HeadsetButton button = get_headset_button();
        switch (button) {
            case BUTTON_VOLINC:
                printf("Volume Increase Button Pressed\n");
                break;
            case BUTTON_VOLDDEC:
                printf("Volume Decrease Button Pressed\n");
                break;
            case BUTTON_PLAYPAUSE:
                printf("Play/Pause Button Pressed\n");
                break;
            case BUTTON_NEXT:
                printf("Next Track Button Pressed\n");
                break;
            case BUTTON_PREV:
                printf("Previous Track Button Pressed\n");
                break;
            default:
                printf("No Button Pressed\n");
        }
    }
    return 0;
}
#endif // TEST